///////////////////////////////////////////////////////////////////////////

#ifndef _UDPSERVER_H_
#define _UDPSERVER_H_

///////////////////////////////////////////////////////////////////////////

#ifndef _SERVERCONNECTION_H_
#include "serverconnection.h"
#endif

#ifndef _MUTEX_H_
#include "mutex.h"
#endif

///////////////////////////////////////////////////////////////////////////


/** UDP server. It sends and receives UDP packets from all clients.
*
*   UDP server determines sender by ID in UDP packet. It redirects
*   the packet to appropriate connection, taken from map<ID, Connection>
*
*   UDP server determines receiver by connection. It sends the packet
*   to appropriate endpoint, taken from map<connection, endpoint>
*
*
*  @author   Pasechnik Roman
*  @since    Jan 16th, 2010
*  @updated  Jan 16th, 2010
*/
class UDPServer
{
///////////////////////////////////////////////////////////////////////////

public:

///////////////////////////////////////////////////////////////////////////


    /** Constructor */
    UDPServer();


///////////////////////////////////////////////////////////////////////////


    /** Start UDP transfers */
    void Start( int _port );


///////////////////////////////////////////////////////////////////////////


    /** Adds connection */
    void AddConnection( ServerConnection& _connection );


    /** Removes connection */
    void RemoveConnection( ServerConnection& _connection );


///////////////////////////////////////////////////////////////////////////


    /** Sends UDP packet to specified endpoint */
    void SendUDP( const NetworkPacket& _packet,
                  const boost::asio::ip::udp::endpoint& _endpoint );


///////////////////////////////////////////////////////////////////////////

private:

///////////////////////////////////////////////////////////////////////////


    /** Opens UDP socket and binds it to port */
    void SetupUDPSocket( int _port );


    /** Starts receiving UDP packets */
    void StartReceiveUDP();


    /** Handle received UDP packet */
    void HandleRecvUDP( const boost::system::error_code& _error,
                        size_t _bytesTransferred );


    /** Finds a connection by ID and redirects packet to it */
    void RedirectUDPToServerConnection( int _connectionID,
                                        const char* _data,
                                        size_t _dataSize );


///////////////////////////////////////////////////////////////////////////


    /** Server connections by their IDs */
    class ConnectionsByIDs : public std::map<int, ServerConnection*>, public Mutex {};
    ConnectionsByIDs m_ConnectionsByIDs;


///////////////////////////////////////////////////////////////////////////


    /** Max buffer size for incoming network packets */
    enum { MAX_BUFFER_SIZE = 1024 };

    /** Buffer for received TCP data */
    char m_RecvBufferUDP[MAX_BUFFER_SIZE];


///////////////////////////////////////////////////////////////////////////


    /** UDP socket */
    boost::asio::ip::udp::socket m_Socket;


    /** UDP endpoint of received packets */
    boost::asio::ip::udp::endpoint m_UDPRecvEndpoint;


///////////////////////////////////////////////////////////////////////////
};


///////////////////////////////////////////////////////////////////////////

#endif

///////////////////////////////////////////////////////////////////////////
